using System;
using System.Collections.Generic;
using System.Text;
using SlimDX;
using System.Xml;
using Barrage.Global;
using SlimDX.DirectInput;

namespace Barrage.GUI.Elements
{
    /// <summary>
    /// Event that's fired when a text input field is modified
    /// </summary>
    /// <param name="itemId">GUIElement id</param>
    /// <param name="value">New field value</param>
    public delegate void GUITextInputHandler(string itemId,string value);
    /// <summary>
    /// A Text input field
    /// </summary>
    public class GUITextInput : GUISelectableElement
    {
        const string XML_WIDTH_ATTRIBUTE = "width";
        const string XML_HEIGHT_ATTRIBUTE = "height";
        const string XML_TITLE_ATTRIBUTE = "title";
        const string XML_TEXT_ATTRIBUTE = "text";
        
        /// <summary>
        /// Event that is fired when the text field is modifield
        /// </summary>
        public event GUITextInputHandler OnInteraction;

        /// <summary>
        /// Item size for mouse interaction
        /// </summary>
        protected Vector2 size;
        /// <summary>
        /// Item size for mouse interaction
        /// </summary>
        public Vector2 Size { get { return size; } }

        bool hovering = false;
        /// <summary>
        /// Tells if the mouse cursor is over the item
        /// </summary>
        public bool Hovering { get { return hovering; } }

        string title;
        /// <summary>
        /// Gets / Sets the title text
        /// </summary>
        public virtual string Title { get { return title; } set { title = value; } }

        string text;
        /// <summary>
        /// Gets / Sets the field text
        /// </summary>
        public virtual string Text { get { return text; } set { text = value; } }

        /// <summary>
        /// Item size (for mouse cursor calculations). Can be overrided
        /// </summary>
        protected virtual Vector2 DefaultSize { get { return new Vector2(100, 100); } }

        /// <summary>
        /// Item constructor
        /// </summary>
        /// <param name="layout">Layout that will hold this item</param>
        /// <param name="template">Template that will be used to render this item</param>
        /// <param name="xn">Xml Node that holds attribute values of this item</param>
        public GUITextInput(GUILayout layout, string template, XmlNode xn)
            : base(layout,template, xn)
        {

            size = GameMath.ParseVector2(XmlHelper.GetXMLAttribute(xn, XML_WIDTH_ATTRIBUTE), XmlHelper.GetXMLAttribute(xn, XML_HEIGHT_ATTRIBUTE), DefaultSize);
            
            text = Language.LanguageManager.Texts[XmlHelper.GetXMLAttribute(xn, XML_TEXT_ATTRIBUTE)];
            title = Language.LanguageManager.Texts[XmlHelper.GetXMLAttribute(xn, XML_TITLE_ATTRIBUTE)];
            
        }

        /// <summary>
        /// \internal Updates item logic
        /// </summary>
        protected override void DoUpdate()
        {
            base.DoUpdate();
            hovering = CheckIntersection();
            if (hovering) Layout.SelectedItemIndex = Order;
            CheckInput();
        }

        /// <summary>
        /// Checks for text input and changes the field accordingly
        /// </summary>
        protected void CheckInput()
        {
            if (Selected)
            {
                bool changed = Keyboard.Instance.TextInput(ref text);

                if (changed)
                    Interact();
            }
        }

        /// <summary>
        /// Checks for mouse intersection
        /// </summary>
        /// <returns>True if there is mouse intersection with this item</returns>
        protected bool CheckIntersection()
        {
            Vector3 mPos = new Vector3(Mouse.Instance.Position,0);
            Vector4 tPos = GameMath.VectorAbs(Vector3.Transform(mPos,Matrix.Invert(motion.WorldMatrix)));

            return ((tPos.X <= size.X / 2f) && (tPos.Y <= size.Y / 2f));
        }

        /// <summary>
        /// \internal Sends an interaction event
        /// </summary>
        public override void Interact()
        {
            if (this.OnInteraction!=null)
                this.OnInteraction.Invoke(Id,Text);
        }
    }
}
